﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bencoder
{
    /// <summary>
    /// Class for decodding bencode
    /// </summary>
    public sealed class Decoder:IDisposable
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public Decoder()
        {
            
        }

        

        private int _Index;
        private string _Data;

        /// <summary>
        /// Decodes bencode format string
        /// </summary>
        /// <param name="data">Bencode data</param>
        /// <returns>List of bencode objects</returns>
        public List<Types.BElement> Decode(string data)
        {
            _Index = 0;
            _Data = data;
            List<Types.BElement> bData = new List<Types.BElement>();
            while (_Index < _Data.Length)
            {
                Types.BElement el = ReadElement();
                bData.Add(el);
            }
            return bData;
        }
        private Types.BInteger ReadInteger()
        {
            try
            {
                string sNum = "";
                char sDigit = '\0';
                if ((sDigit = _Data[_Index++]) != 'i')
                    throw new FormatException("Unexpected type '" + sDigit + "'.");

                while ((sDigit = _Data[_Index++]) != 'e')
                {
                    sNum += sDigit;
                }
                long data = Convert.ToInt64(sNum);
                return new Types.BInteger(data);
            }
            catch (Exception ex)
            {
                throw new BencoderException("Invalid bencode integer format", ex);
            }
        }
        private Types.BString ReadString()
        {
            try
            {
                string sNum = "";
                char sDigit = '\0';
                while ((sDigit = _Data[_Index++]) != ':')
                {
                    sNum += sDigit;
                }
                int stringLenght = Convert.ToInt32(sNum);
                string data = _Data.Substring(_Index, stringLenght);
                _Index += stringLenght;
                return new Types.BString(data);
            }
            catch (Exception ex)
            {
                throw new BencoderException("Invalid bencode string format", ex);
            }
        }
        private Types.BElement ReadElement()
        {
            switch (_Data[_Index])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    return ReadString();
                case 'i':
                    return ReadInteger();
                case 'd':
                case 'l':
                    throw new NotImplementedException();
                default:
                    throw new NotSupportedException("Type '" + _Data[_Index] + "' is not supported.");
            }
        }

        public void Dispose()
        {
            
        }
    }
}
